/*
 *    This file is part of BlobDB.
 *
 *    BlobDB is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    BlobDB is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with BlobDB.  If not, see <http://www.gnu.org/licenses/>.
 *    
 *    Copyright(c) 2011 Michael Kankkonen
 *    http://www.vnetcon.org
 */


package org.vnetcon.blobdb.database.util;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import org.vnetcon.blobdb.database.SQLException;

public class ColumnInfo extends InfoBase {

	int iCursor = 0;
	
	public static final int CHAR = 1;
	public static final int NUMBER = 2;
	public static final int DECIMAL = 3;
	public static final int DATE = 4;
	public static final int TIME = 5;
	public static final int FOREIGN_KEY = 6;

	// YYYYMMDD
	public static final int DATE_SIZE = 8;
	// HHMMSS
	public static final int TIME_SIZE = 6;

	
	private ArrayList<String> colName = new ArrayList<String>();
	private ArrayList<Integer> colType = new ArrayList<Integer>();
	private ArrayList<Integer> colSize = new ArrayList<Integer>();
	private ArrayList<Integer> decSize = new ArrayList<Integer>();
	private Hashtable<String, String> colValue = new Hashtable<String, String>();
	private ArrayList<String> colValueOrder = new ArrayList<String>();

	private Hashtable<String, Integer> colNameIndex = new Hashtable<String, Integer>();
	
	public ColumnInfo(){
	}

	public void setColValue(String colName, String value) throws SQLException{
		if(getColumnIndex(colName) == -1){
			throw new SQLException("Column does not extist: " + colName);
		}
		if(!colValue.containsKey(colName)){
			colValueOrder.add(colName);
			colValue.put(colName, value);
		}else{
			throw new SQLException("Duplicate column value set in update: " + colName);
		}
	}

	
	public List<String> getUpdateColumns(){
		return this.colValueOrder;
	}

	public String getColValue(String colName) throws SQLException{
		if(getColumnIndex(colName) == -1){
			throw new SQLException("Column does not extist: " + colName);
		}
		return colValue.get(colName);
	}
	
	public void parseInfo(byte[] columnInfo) throws SQLException {

		try {
			iCursor = 0;
			int iCounter = 0;
			int iBuf = 0;
			byte buf[];

//			while (iBuf > -1 && iCounter < 16) {
			while (iBuf > -1) {
				String strColName = null;
				iBuf = this.readInt(columnInfo, iCursor);
				iCursor = iCursor + 4;

				if (iBuf < 0) {
					continue;
				}

				// System.out.println("parseInfo 2.1.1: " + iBuf);
				buf = this.readBytes(columnInfo, iCursor, iBuf);
				iCursor = iCursor + iBuf;
				strColName = new String(buf);
				colName.add(strColName);
				iBuf = this.readInt(columnInfo, iCursor);
				iCursor = iCursor + 4;
				colType.add(iBuf);
				iBuf = this.readInt(columnInfo, iCursor);
				iCursor = iCursor + 4;
				colSize.add(iBuf);
				iBuf = this.readInt(columnInfo, iCursor);
				iCursor = iCursor + 4;
				decSize.add(iBuf);
				colNameIndex.put(strColName, iCounter);
				iCounter++;
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new SQLException(ex.getMessage());
		}
		
	}

	public void addColumn(String name, int type, int size, int decimals){
		colName.add(name);
		colType.add(type);
		colSize.add(size);
		decSize.add(decimals);
		colNameIndex.put(name, colName.size() - 1);
	}

	
	public byte[] getAsByteArray() throws Exception {
		int i = 0;
		int bufSize = 0;
		byte byteBuf[] = null;
		iCursor = 0;
		byte buf[] = null;
		
		i = 0;
		while(i < colName.size()){
			String name = colName.get(i);
			byteBuf = name.getBytes();
			bufSize += byteBuf.length + 16;
			i++;
		}
		
		buf = new byte[bufSize + 4];
		i = 0;
		while(i < colName.size()){
			String name = colName.get(i);
			int type = colType.get(i);
			int size = colSize.get(i);
			int decimals = decSize.get(i);
			
			byteBuf = name.getBytes();
			this.writeInt(buf, iCursor, byteBuf.length);
			iCursor = iCursor + 4;
			this.writeBytes(buf, iCursor, byteBuf);
			iCursor = iCursor + byteBuf.length;
			this.writeInt(buf, iCursor, type);
			iCursor = iCursor + 4;
			this.writeInt(buf, iCursor, size);
			iCursor = iCursor + 4;
			this.writeInt(buf, iCursor, decimals);
			iCursor = iCursor + 4;
			i++;
		}

		this.writeInt(buf, iCursor, -1);
		
		return buf;
	}

	public List<String> getColumnNames(){
		return this.colName;
	}
	
	public int getColumnIndex(String colName) throws SQLException{
		int iRet = -1;
		if(colNameIndex.containsKey(colName)){
			iRet = colNameIndex.get(colName);
		}else{
			throw new SQLException("Invalid column name: " + colName);
		}
		return iRet;
	}

	public int getColumnStartPosition(String colName) throws SQLException {
		int iRet = 0;
		int i = 0;
		int iColIndex = getColumnIndex(colName);
		
		while(i < iColIndex){
			iRet += colSize.get(i);
			i++;
		}
		
		return iRet;
	}

	public int getColumnLength(String colName) throws SQLException {
		int iRet = 0;
		int iColIndex = getColumnIndex(colName);
		iRet = colSize.get(iColIndex);
		return iRet;
	}

	public int getColumnDecimals(String colName) throws SQLException {
		int iRet = 0;
		int iColIndex = getColumnIndex(colName);
		iRet = decSize.get(iColIndex);
		return iRet;
	}
	
	public int getColumnType(String colName) throws SQLException {
		int iRet = 0;
		int iColIndex = getColumnIndex(colName);
		iRet = colType.get(iColIndex);
		return iRet;
	}
	
	public byte[] formatForDatabase(String colName, byte[] value) throws SQLException {
		int iColType = getColumnType(colName);
		
		if(iColType == CHAR){
		}

		if(iColType == NUMBER){
		}
		
		if(iColType == DECIMAL){
		}
		
		if(iColType == DATE){
		}
		
		if(iColType == TIME){
		}
		
		return null;
	}

	public byte[] formatForDatabase(String colName, String value) throws SQLException {
		return formatForDatabase(colName, value.getBytes());
	}
	
	public byte[] formatForDatabase(String colName, long value) throws SQLException {
		StringBuffer sb = new StringBuffer();
		sb.append(value);
		return formatForDatabase(colName, sb.toString().getBytes());
	}
	
	public byte[] formatForDatabase(String colName, double value) throws SQLException {
		StringBuffer sb = new StringBuffer();
		sb.append(value);
		return formatForDatabase(colName, sb.toString().getBytes());
	}
	
}
